package Lab.Five.WallOfClutter;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class Lab5WallOfClutterWriteActivity extends Activity implements OnClickListener
{
	// Fields.
	Button m_bSend;
	EditText m_inputText; 
	TextView m_textView;
	DatabaseHelper m_dh;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.mainwrite);
	    
	    m_dh = new DatabaseHelper(this);
	    m_bSend = (Button)findViewById(R.id.sendButton);
	    m_inputText = (EditText)findViewById(R.id.textInput);
	    m_textView = (TextView)findViewById(R.id.textViewWrite);
	    
	    m_textView.setText("0 / 150");

	    
	    m_bSend.setOnClickListener(this);
	    m_inputText.addTextChangedListener(new TextWatcher()
	    {
			public void onTextChanged(CharSequence s, int start, int before, int count) 
			{
			}
			public void beforeTextChanged(CharSequence s, int start, int count, int after) 
			{		
			}
			public void afterTextChanged(Editable s) 
			{
				m_textView.setText(s.length() + " / " + "150");
			}
		});
	}

	public void onClick(View v) 
	{
		if (v.getId() == R.id.sendButton)
		{			
			String textMessage = m_inputText.getText().toString();
			
			ErrorHandling.newDebugEvent("TextMessage: " + textMessage);
			
			Context context = getApplicationContext();
			int duration = 5000;
			
			if (textMessage.equalsIgnoreCase("") == true)
			{
				String text = "Error: The message was not sent.\n Can't send empty messages.";
				Toast toast = Toast.makeText(context, text, duration);
				toast.show();
			}
			else
			{
				new sendNewMessage().execute(textMessage);
			}
		}
	}
	
	private class Client implements Runnable
	{
		// Fields.
		private String IP = "194.47.174.57";
		private int PORT = 9050;
		private InetAddress m_serverAddr = null;
		private DatagramSocket m_socket = null;
		private byte[] m_buff = null;
		private DatagramPacket m_packet = null;
		
		public void run() 
		{
			try
			{
		        // Set the server address.
				m_serverAddr = InetAddress.getByName(IP);
				
				// Instantiate the socket.
				m_socket = new DatagramSocket();
			}
			catch (Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterWrite//Sendmessage//Client//tryCatch: Exception", e.toString());
			}
		}
		
		public void sendMessage(String a_text)
		{
			// Data to be sent.
			String data = "MSGAD;" + a_text;
			m_buff = (data).getBytes();
			
			try
			{
				// Create the packet.
				m_packet = new DatagramPacket(m_buff, m_buff.length, m_serverAddr, PORT);
					
				// Send the data.
				m_socket.send(m_packet);
					
				byte[] message = new byte[1500];
				m_packet = new DatagramPacket(message, message.length);
			}
			catch(Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterWrite//Sendmessage//Client//tryCatch: Exception", e.toString());
			}
		}
		
		public int getMaxId()
		{
			try
			{
				// Data to be sent.
				m_buff = ("MAXID;").getBytes();
					
				// Create the packet.
				m_packet = new DatagramPacket(m_buff, m_buff.length, m_serverAddr, PORT);
					
				// Send the data.
				m_socket.send(m_packet);
					
				byte[] message = new byte[1500];
				m_packet = new DatagramPacket(message, message.length);
					
				m_socket.receive(m_packet);
					
				String text = new String(m_packet.getData());
					
				// Split away the extra data that was added to fill the byte array.
				text = text.split(";")[0];
					
				// Split so you only get the ID.
				int tempId = Integer.valueOf(text.split(" ")[1]);

				return tempId;
			}
			catch (Exception e)
			{
				Log.d("debug-event", e.toString());
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterWrite//SendMessage//Client//tryCatch: Exception", e.toString());
			}
			return -1;
		}
		
		public List<Message> getNewMessages(int a_oldId, int a_newId)
		{
			List<Message> messageList = new ArrayList<Message>();
			
			try
			{
				for (int i = a_oldId; i <= a_newId; i++)
				{
					String dataString = "GETID " + i + ";";
							
					// Data to be sent.
					m_buff = (dataString).getBytes();
						
					// Create the packet.
					m_packet = new DatagramPacket(m_buff, m_buff.length, m_serverAddr, PORT);
						
					// Send the data.
					m_socket.send(m_packet);
						
					byte[] message = new byte[1500];
					m_packet = new DatagramPacket(message, message.length);
						
					m_socket.receive(m_packet);
						
					String text = new String(m_packet.getData());
						
					// Split at empty space to get the message length.
					String messageInfo = text.split(";")[0];
						
					int messageLength = Integer.valueOf(messageInfo.split(" ")[2]);
					int messageId = Integer.valueOf(messageInfo.split(" ")[1]);
						
					// Get only the message part of the text.
					int elements = text.split(";").length;
					String messageText = "";
						
					// If you get more than 2 elements it means the message contains more than one ; so add it back.
					if (elements > 2)
					{
						for (int z = 1; z < elements; z++)
						{
							messageText = messageText + text.split(";")[z];
						}
					}
					else
					{
						messageText = text.split(";")[1];
					}
	
					//substring the message length.
					messageText = messageText.substring(0, messageLength);
						
					Message messageObject = new Message(messageId, messageText);
						
					messageList.add(messageObject);
				}
			}
			catch (Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutter//DownloadNewMessages//Client//tryCatch: Exception", e.toString());
			}
			return messageList;
		}
	}
	
	private class sendNewMessage extends AsyncTask<String, Integer, Boolean>
	{

		@Override
		protected Boolean doInBackground(String... params) 
		{
			String textMessage = params[0];
			
			// Ready the client for use.
			Client client = new Client();
			client.run();
			
			int oldId = client.getMaxId();
			
			if (oldId >= 0)
			{
				// Send the message.
				client.sendMessage(textMessage);
				
				// Check if the maxId increased.
				int newId = client.getMaxId();
				
				if (newId > oldId + 1)
				{					
					List<Message> newMessagesList = client.getNewMessages(oldId, newId);
					boolean matchFound = false;
					int messId = 0;
					
					for (Message mess : newMessagesList)
					{
						if (mess.getMessage().equalsIgnoreCase(textMessage));
						{
							messId = mess.getId();
							matchFound = true;
						}
					}	

					if (matchFound == true)
					{
						Message mess = new Message(messId, textMessage);
						StoreData(mess);
						return true;
					}
					else 
					{
						return false;
					}
				}
				else if (newId == oldId + 1)
				{
					Message mess = new Message(newId, textMessage);
					StoreData(mess);
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
		
		@Override
		protected void onPostExecute(Boolean result) 
		{
			Context context = getApplicationContext();
			int duration = 5000;
			
			if (result == true)
			{
				String text = "Success: Message sent.";
				Toast toast = Toast.makeText(context, text, duration);
				toast.show();
				m_inputText.setText("");
			}
			else
			{
				String text = "Error: The message was not sent.";
				Toast toast = Toast.makeText(context, text, duration);
				toast.show();
			}
		}
		
		private void StoreData(Message a_message)
		{
			m_dh.insertMessage(a_message);
		}
	}
}
